//request.js文件用来封装我们的axios
//
// qs vue 插件
// 里面有用到qs，这里我门讲解下他的作用：
//
// get方法：我们通过定义一个get函数，get函数有两个参数，第一个参数表示我们要请求的url地址，第二个参数是我们要携带的请求参数。get函数返回一个promise对象，当axios其请求成功时resolve服务器返回 值，请求失败时reject错误值。最后通过export抛出get函数。
//
// post方法：原理同get基本一样，但是要注意的是，post方法必须要使用对提交从参数对象进行序列化的操作，所以这里我们通过node的qs模块来序列化我们的参数。这个很重要，如果没有序列化操作，后台是拿不到你提交的数据的。这就是文章开头我们import QS from ‘qs’;的原因。
//
// 简单来说，qs 是一个增加了一些安全性的查询字符串解析和序列化字符串的库。
//
// 在项目中使用命令行工具输入：npm install qs
// 安装完成后在需要用到的组件中：import qs from 'qs’
// 具体使用中我查看了：qs.parse()和qs.stringify()
//
// 这两种方法虽然都是序列化，但是还是有区别的。
// qs.parse()是将URL解析成对象的形式
// qs.stringify()是将对象 序列化成URL的形式，以&进行拼接

//要注意的是，上面的this.$message方法，是我引入的element库中的轻提示组件，你根据你的ui库，对应使用你的一个提示组件。
//
// 这里说一下token，一般是在登录完成之后，将用户的token通过localStorage或者cookie存在本地，然后用户每次在进入页面的时候（即在main.js中），会首先从本地存储中读取token，如果token存在说明用户已经登陆过，则更新vuex中的token状态。然后，在每次请求接口的时候，都会在请求的header中携带token，后台人员就可以根据你携带的token来判断你的登录是否过期，如果没有携带，则说明没有登录过。

//axios.get()方法和axios.post()在提交数据时参数的书写方式还是有区别的。区别就是，get的第二个参数是一个{}，
// 然后这个对象的params属性值是一个参数对象的。而post的第二个参数就是一个参数对象。两者略微的区别要留意哦！

// 封装axios
import axios from "axios";
// 序列化
import { ElMessage } from "element-plus";
import router from "../router";

// 使用自定义的配置文件发送请求
const axiosService = axios.create({
  // baseURL: 'http://127.0.0.1:20000',
  baseURL: import.meta.env.VITE_API_BASE,
  // baseURL: '/api',
  //超时时间
  timeout: 80000,
});

// post请求的时候，我们需要加上一个请求头，所以可以在这里进行一个默认的设置，即设置post的请求头为
axios.defaults.headers.post["Content-Type"] =
  "application/x-www-form-urlencoded;charset=UTF-8";
axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";

// 添加请求拦截器
axiosService.interceptors.request.use(
  // function (config) {
  //     // 每次发送请求之前判断vuex中是否存在token
  //     // 如果存在，则统一在http请求的header都加上token，这样后台根据token判断你的登录情况
  //     // 即使本地存在token，也有可能token是过期的，所以在响应拦截器中要对返回状态进行判断

  //     // const token = store.getters.getToken();
  //     const token = localStorage.getItem(SystemConstant.TOKEN_KEY)
  //     if (token) {
  //         // 已经登录成功，统一添加token
  //         // config.headers.Authorization = `Bearer ${token}`
  //         config.headers.Authorization = `${token}`
  //     }
  //     // token && (config.headers.Authorization = token);
  //     return config;
  // },
  function (config) {
    const token = localStorage.getItem(SystemConstant.TOKEN_KEY);
    if (token) {
      config.headers.Authorization = token;
    }
    return config;
  },
  function (error) {
    // 对请求错误做些什么
    ElMessage.error("请求错误，请重新登陆");
    return Promise.reject(error);
  }
);

// 这里说一下token，一般是在登录完成之后，将用户的token通过localStorage或者cookie存在本地，
// 然后用户每次在进入页面的时候（即在main.js中），会首先从本地存储中读取token，如果token存在说明用户已经登陆过，
// 则更新vuex中的token状态。然后，在每次请求接口的时候，都会在请求的header中携带token，
// 后台人员就可以根据你携带的token来判断你的登录是否过期，如果没有携带，则说明没有登录过。
// 添加响应拦截器
axiosService.interceptors.response.use(
  function (response) {
    // console.log('111', router.currentRoute.value.name);
    if (response.data.code == 99999) {
      // ElMessage.success(response.data.msg);
    }
    // 10101 代表後端沒有token
    if (response.data.code === 10101) {
      // 优化点：添加跳转前的提示
      ElMessage.error("会话已过期，请重新登录");
      router.push({ name: "login" });
    }
    return Promise.resolve(response);
  },

  function (error) {
    console.log("响应拦截器-错误");
    console.log(error);

    if (error.response && error.response.status) {
      // 统一 token 的键名
      const tokenKey = window.SystemConstant?.TOKEN_KEY || "authToken";
      const status = error.response.status;

      if (status === 401) {
        localStorage.removeItem(tokenKey);
        ElMessage.error("登录过期，请重新登录");
        // 跳转到登录页面
        window.location.reload();
        router.push({ name: "login" }).then(() => {
          window.location.reload();
        });

        return Promise.reject(error);
      } else if (status === 403) {
        ElMessage.error("权限不足，请联系管理员");
      } else if (status === 404) {
        ElMessage.error("请求的资源不存在");
      } else if (status === 500) {
        ElMessage.error("服务器错误，请联系管理员");
      } else {
        return Promise.reject(error.response);
      }
    }
    return Promise.reject(error);
  }
);

export default axiosService;
